package tsg.physics;

import java.util.ArrayList;

import tsg.shape.Rectangle;
import tsg.util.Point;


public class Collision 
{
	/**
	 * Performs the Ray-Casting algorithm to determine if the pointInQuestion 
	 * lies inside the polygon defined by the list of Points
	 * 
	 * @param pointInQuestion
	 * @param polygonPoints
	 * @return boolean
	 */
	public static boolean pointLiesInPolygon(Point pointInQuestion, ArrayList<Point> polygonPoints)
	{
		boolean result 				= false;
		int 	horizontalHitCount 	= 0;
		int 	verticalHitCount	= 0;
		int     aX                  = 0;
		int     aY                  = 0;
		int     bX                  = 0;
		int     bY                  = 0;
		int     cX                  = pointInQuestion.getX();
		int     cY                  = pointInQuestion.getY();
		
		// We must have at least 3 points to define a polygon
		if(polygonPoints.size() >= 3)
		{
			Point pointA = null;
			Point pointB = null;
		
		
			for(int i=0; i<polygonPoints.size(); i++)
			{		
				
				// Grab pointA and pointB for this section of the polygon
				pointA = polygonPoints.get(i);
				
				if(i==0)
				{
					pointB = polygonPoints.get(polygonPoints.size()-1);
				}
				else
				{



					pointB = polygonPoints.get(i-1);
				}
				
				// Grab the coordinates of our points
				aX = pointA.getX();
				aY = pointA.getY();
				bX = pointB.getX();
				bY = pointB.getY();
				
				
				
				// This is how we tell if we have a hit:
				//
				// Lets say we have the following situation
				//
				// (aX, aY)
				//     o
				//      \		(cX, cY)
				//       \        	o <-- PointInQuestion
				//        \
				//         o
				//		(bX, bY)
				// 
				// We can boil this down to 2 sets of 1 dimensional problems
				// 
				// 1) 
				//	   (aY)
				//     	o
				// 		|	       (cY)
				// 		|			o <-- PointInQuestion
				// 		|
				// 		o
				//	   (bY)
				// 
				// 2)
				//	  (aX)     (bX)
				// 		o-------o	
				//
				//			       (cX)
				//					o <-- Point in Question
				// 
				// if the PointInQuestion lies between the X's in PointA and PointB then increment the vertical   hit count
				// if the PointInQuestion lies between the Y's in PointA and PointB then increment the horizontal hit count
				// if either of the vertical or horizontal hit counts are odd, the point lies in the polygon
		
				
				// Are the X's mutually exclusive?
				if(	(cX >= aX && cX <= bX)	||
					(cX >= bX && cX <= aX)	)
				
				{
					// If so, we have a hit
					verticalHitCount = verticalHitCount + 1;
				}
				
				
				// Are the Y's mutually exclusive?
				if(	(cY >= aY && cY <= bY)	||
					(cY >= bY && cY <= aY)	)
				
				{
					// If so, we have a hit
					horizontalHitCount = horizontalHitCount + 1;
				}
			}
		}
		
		
		// If the horizontal or vertical hit count are odd
		if(	horizontalHitCount 	% 2 != 0	||
			verticalHitCount 	% 2 != 0	)
		{
			result = true;
		}
		
		// Return the result
		return result;
	}
	
	
	/**
	 * Returns whether or not the given point lies in the given rectangle
	 * 
	 * @param point
	 * @param rectangle
	 * @return boolean
	 */
	public static boolean pointLiesInRectangle(Point point, Rectangle rectangle)
	{
		boolean result = false;
		
		if( point.getX() >= rectangle.getX() 							&& 
			point.getY() >= rectangle.getY()							&&
			point.getX() <= rectangle.getX() + rectangle.getWidth()		&&
			point.getY() <= rectangle.getY() + rectangle.getHeight()	)
		{
			result = true;
		}
		
		return result;
	}
	
	/**
	 * If the two rectangles intersect, return true. This includes if one 
	 * rectangle is totally enclosed by the other.
	 * 
	 * @param rectangleA
	 * @param rectangleB
	 * @return boolean
	 */
	public static boolean rectanglesIntersect(Rectangle rectangleA, Rectangle rectangleB)
	{
		boolean result 		= false;
		
		int		aX1			= rectangleA.getX();
		int		aX2			= rectangleA.getX() + rectangleA.getWidth();
		int		aY1			= rectangleA.getY();
		int		aY2			= rectangleA.getY() + rectangleA.getHeight();
		
		int		bX1			= rectangleB.getX();
		int		bX2			= rectangleB.getX() + rectangleB.getWidth();
		int		bY1			= rectangleB.getY();           
		int		bY2			= rectangleB.getY() + rectangleB.getHeight();
		
		// The above definitions are for the rectangle coordinates.
		//
		// E.g.
		//
		// (aX1, aY1)			(aX2, aY1)
		//      o-------------------o
		//		|					|
		//		|					|
		//		|		(bX1, bY1)	|		(bX2, bY1)
		//		|			o-------|-----------o
		//		|			|		|           |
		//		|			|		|           |
		//		|			|		|           |
		//		|			|		|           |
		//      o-----------|-------o           |
		// (aX1, aY2)		|	(aX2, aY2)      |
		//                  |                   |
		//                  |					|
		//					o-------------------o
		//				(bX1, bY2)			(bX2, bY2)
		
		// Are the X's mutually exclusive?
		if(	(bX1 >= aX1 && bX1 <= aX2) 	|| 
			(bX2 >= aX1 && bX2 <= aX2)	)
		{
			
			// If so then let's check whether or
			// not the Y's are mutually exclusive?
			if(	(bY1 >= aY1 && bY1 <= aY2) 	|| 
				(bY2 >= aY1 && bY2 <= aY2)	)
			{
				// if so, we have a collision
				result = true;
			}
		}
		
		return result;
	}
}
